1 //+-----------------------------------------------------------------------
3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // Implements the OleDocumentView class of PresentationHost.
12 // Ported Windows->DevDiv. See SourcesHistory.txt.
14 //------------------------------------------------------------------------
16 #include "Precompiled.hxx"
17 #include "OleDocumentView.hxx"
18 #include "OleDocument.hxx"
19 #include "OleInPlaceActiveObject.hxx"
20 #include "ErrorPage.hxx"
21 #include "Utilities.hxx"
24 extern HINSTANCE g_hInstance
;
27 //******************************************************************************
29 // COleDocumentView::COleDocumentView()
31 //******************************************************************************
33 COleDocumentView::COleDocumentView(__in COleDocument
*pOleDoc
):
34 m_pInPlaceSite(0), m_pInPlaceFrame(0), m_pInPlaceUIWindow(0), m_FrameInfo(),
35 m_fShow(false), m_fUIActive(false), m_fInPlaceActive(false), m_Rect(),
37 m_hDocObjMenu(0), m_hSharedMenu(0), m_hViewMenu(0), m_hOleMenu(0)
39 //This is interface aggregation, don't AddRef the OleDoc
43 //******************************************************************************
45 // COleDocumentView::~COleDocumentView()
47 //******************************************************************************
49 COleDocumentView::~COleDocumentView()
51 //Should already have been destroyed when we remove menus. Calling it here
52 //to be on the safe side
53 DestroyMenuResources();
55 ReleaseInterface(m_pInPlaceSite
);
56 ReleaseInterface(m_pInPlaceFrame
);
57 ReleaseInterface(m_pInPlaceUIWindow
);
60 //******************************************************************************
62 // IUnknown Implementation
64 //******************************************************************************
66 //******************************************************************************
68 // COleDocumentView::QueryInterface
70 //******************************************************************************
72 STDMETHODIMP
COleDocumentView::QueryInterface(REFIID riid
,
73 __out LPVOID
*ppReturn
)
75 return m_pOleDoc
->QueryInterface(riid
, ppReturn
);
78 //******************************************************************************
80 // COleDocumentView::AddRef
82 //******************************************************************************
84 STDMETHODIMP_(DWORD
) COleDocumentView::AddRef()
86 return m_pOleDoc
->AddRef();
89 //******************************************************************************
91 // COleDocumentView::Release
93 //******************************************************************************
95 STDMETHODIMP_(DWORD
) COleDocumentView::Release()
97 return m_pOleDoc
->Release();
100 //******************************************************************************
102 // COleDocumentView::SetInPlaceSite()
104 //******************************************************************************
106 STDMETHODIMP
COleDocumentView::SetInPlaceSite(__in_opt IOleInPlaceSite
*pNewSite
)
114 CKHR(DeactivateUI());
117 if (m_fInPlaceActive
)
119 CKHR(DeactivateInPlace());
124 ReleaseInterface(m_pInPlaceFrame
);
127 if (m_pInPlaceUIWindow
)
129 ReleaseInterface(m_pInPlaceUIWindow
);
132 ReleaseInterface(m_pInPlaceSite
);
135 m_pInPlaceSite
= pNewSite
;
139 m_pInPlaceSite
->AddRef();
143 m_FrameInfo
.cb
= sizeof(m_FrameInfo
);
145 CKHR(m_pInPlaceSite
->GetWindowContext(&m_pInPlaceFrame
,
157 //******************************************************************************
159 // COleDocumentView::GetInPlaceSite()
161 //******************************************************************************
163 STDMETHODIMP
COleDocumentView::GetInPlaceSite(__out IOleInPlaceSite
**ppInPlaceSite
)
167 CK_PARG(ppInPlaceSite
)
168 *ppInPlaceSite
= m_pInPlaceSite
;
172 (*ppInPlaceSite
)->AddRef();
180 //******************************************************************************
182 // COleDocumentView::GetDocument()
184 //******************************************************************************
186 STDMETHODIMP
COleDocumentView::GetDocument(__out IUnknown
**ppUnk
)
192 CKHR(m_pOleDoc
->QueryInterface(IID_IUnknown
, (void **)ppUnk
));
197 //******************************************************************************
199 // COleDocumentView::SetRect()
201 //******************************************************************************
203 void COleDocumentView::MoveViewportHelper(int x
, int y
, int nWidth
, int nHeight
)
205 // update the dimensions of the top dockobj hwnd using the dimensions provided
207 // A 0x0 rect is passed to IOleDocumentView::SetRect() or IOleInPlaceObject::SetObjectRects()
208 // (depending on the hosting mode) when the top-level window is minimized. This appears to be a bug
209 // in the ATL host, which gets 0x0 in its WM_SIZE handler but ignores the SIZE_MINIMIZED flag.
210 // IE probably does something similar. But normally child windows are not resized or moved when the
211 // top-level window is minimized.
212 if(nWidth
> 0 || nHeight
> 0)
214 // Drawing optimization (last param of MoveWindow): don't paint the background of the top window if the
215 // RBW is present. (In spite of the WS_CLIPCHILDREN style, this drawing does take place, at least
217 MoveWindow(m_pOleDoc
->m_hwndTop
, x
, y
, nWidth
, nHeight
, !m_pOleDoc
->ApplicationHelper());
218 if(m_pOleDoc
->ApplicationHelper())
220 // update dimensions of the RBW window. Note, x,y of RBW should always be
221 // 0,0 relative to the top dockobj hwnd
222 (m_pOleDoc
->ApplicationHelper())->Move(0, 0, nWidth
, nHeight
);
225 CErrorPage::SetRect(x
, y
, nWidth
, nHeight
);
229 STDMETHODIMP
COleDocumentView::SetRect(__in LPRECT pRect
)
237 // MoveViewportHelper expects x, y, width, height
238 MoveViewportHelper(m_Rect
.left
,
240 m_Rect
.right
- m_Rect
.left
,
241 m_Rect
.bottom
- m_Rect
.top
);
249 //******************************************************************************
251 // COleDocumentView::GetRect()
253 //******************************************************************************
255 STDMETHODIMP
COleDocumentView::GetRect(__out LPRECT pRect
)
268 //******************************************************************************
270 // COleDocumentView::SetRectComplex()
272 //******************************************************************************
274 STDMETHODIMP
COleDocumentView::SetRectComplex(LPRECT
/* prcView */,
275 LPRECT
/* prcHScroll */,
276 LPRECT
/* prcVScroll */,
277 LPRECT
/* prcSizeBox */)
282 //******************************************************************************
284 // COleDocumentView::Show()
286 //******************************************************************************
287 void COleDocumentView::ShowHelper(bool fShow
)
289 ShowWindow(m_pOleDoc
->m_hwndTop
,fShow
);
290 if(m_pOleDoc
->ApplicationHelper())
292 (m_pOleDoc
->ApplicationHelper())->Show(fShow
);
296 //ASSERT(CErrorPage::IsActive());
297 //SP2: Not true anymore. UI Activation now happens before loading any managed code.
303 STDMETHODIMP
COleDocumentView::Show(BOOL bShow
)
309 //if the object is not in-place active, make it that way
310 if (!m_fInPlaceActive
)
319 //if the object is UI active, make remove that state
332 //******************************************************************************
334 // COleDocumentView::UIActivate()
336 //******************************************************************************
338 STDMETHODIMP
COleDocumentView::UIActivate(BOOL bActivate
)
345 return DeactivateUI();
348 //******************************************************************************
350 // COleDocumentView::ActivateUI()
352 //******************************************************************************
354 STDMETHODIMP
COleDocumentView::ActivateUI()
358 //set the active object either one of these could be good
361 m_pInPlaceFrame
->SetActiveObject(m_pOleDoc
->m_pOleInPlaceActiveObject
,
365 if (m_pInPlaceUIWindow
)
367 m_pInPlaceUIWindow
->SetActiveObject(m_pOleDoc
->m_pOleInPlaceActiveObject
,
377 m_pInPlaceSite
->OnUIActivate();
379 CKHR(InsertMergedMenus());
381 SetFocus(m_pOleDoc
->m_hwndTop
);
389 //******************************************************************************
391 // COleDocumentView::DeactivateUI()
393 //******************************************************************************
395 STDMETHODIMP
COleDocumentView::DeactivateUI()
401 //remove the active object either one of these could be good
404 m_pInPlaceFrame
->SetActiveObject(NULL
, NULL
);
407 if (m_pInPlaceUIWindow
)
409 m_pInPlaceUIWindow
->SetActiveObject(NULL
, NULL
);
414 m_pInPlaceSite
->OnUIDeactivate(FALSE
);
420 //******************************************************************************
422 // COleDocumentView::Open()
424 //******************************************************************************
426 STDMETHODIMP
COleDocumentView::Open(void)
431 //******************************************************************************
433 // COleDocumentView::CloseView()
435 //******************************************************************************
437 STDMETHODIMP
COleDocumentView::CloseView(DWORD
/* dwReserved */)
439 SetInPlaceSite(NULL
);
443 //******************************************************************************
445 // COleDocumentView::SaveViewState()
447 //******************************************************************************
449 STDMETHODIMP
COleDocumentView::SaveViewState(IStream
* /* pStream */)
454 //******************************************************************************
456 // COleDocumentView::ApplyViewState()
458 //******************************************************************************
460 STDMETHODIMP
COleDocumentView::ApplyViewState(IStream
* /* pStream */)
465 //******************************************************************************
467 // COleDocumentView::Clone()
469 //******************************************************************************
471 STDMETHODIMP
COleDocumentView::Clone(IOleInPlaceSite
* /* pIPSite */,
472 IOleDocumentView
** /* ppView */)
477 //******************************************************************************
479 // COleDocumentView::ActivateInPlace()
481 //******************************************************************************
482 void COleDocumentView::SetParentHelper(HWND hwndParent
)
484 // if hwndParent == NULL We are going away
485 if (hwndParent
== NULL
)
487 SetWindowLong(m_pOleDoc
->m_hwndTop
, GWL_STYLE
, WS_OVERLAPPED
| WS_CLIPSIBLINGS
| WS_DISABLED
);
491 SetWindowLong(m_pOleDoc
->m_hwndTop
, GWL_STYLE
, WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
);
494 //This will notify the managed window to set up the parent or cleanup during shutdown
495 //If we don't detach the parent window during shutdown, we will end up processing WM_DESTROY
496 //twice since we close windows when Application is shutdown which posts one msg and when the
497 //browser window is closed, the managed child window will get another one.
498 //Detach the parent window to avoid that.
499 SetParent(m_pOleDoc
->m_hwndTop
, hwndParent
);
500 SetWindowPos(m_pOleDoc
->m_hwndTop
, 0,0,0,0,0, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
);
505 STDMETHODIMP
COleDocumentView::ActivateInPlace()
509 m_fInPlaceActive
= TRUE
;
513 // tell the site we are in-place activating
514 m_pInPlaceSite
->OnInPlaceActivate();
516 m_pInPlaceSite
->GetWindow(&hwndParent
);
518 SetParentHelper(hwndParent
);
524 //******************************************************************************
526 // COleDocumentView::DeactivateInPlace()
528 //******************************************************************************
530 STDMETHODIMP
COleDocumentView::DeactivateInPlace()
532 m_fInPlaceActive
= FALSE
;
536 // tell the site we are in-place deactivating
537 m_pInPlaceSite
->OnInPlaceDeactivate();
540 //set the parent to NULL
541 SetParentHelper(NULL
);
547 //******************************************************************************
549 // COleDocumentView::InsertMergedMenus()
551 //******************************************************************************
554 #define MSGFLT_REMOVE 2
555 typedef BOOL (WINAPI
*PFChangeWindowMessageFilter
)(__in UINT message
, __in DWORD dwFlag
);
556 typedef BOOL (WINAPI
*PFChangeWindowMessageFilterEx
)(HWND hwnd
, UINT message
, DWORD action
, __inout_opt
void* /*PCHANGEFILTERSTRUCT*/ pChangeFilterStruct
);
558 BOOL WINAPI
CallOldChangeWindowMessageFilter(HWND hwnd
, UINT message
, DWORD action
, __inout_opt
void* /*PCHANGEFILTERSTRUCT*/ pChangeFilterStruct
)
560 static PFChangeWindowMessageFilter pfCWMF
;
563 GetProcAddress(L
"User32.dll", "ChangeWindowMessageFilter", &pfCWMF
);
565 return (*pfCWMF
)(message
, action
);
568 HRESULT
COleDocumentView::InsertMergedMenus()
570 EventWriteWpfHostUm_MergingMenusStart();
576 IProtectedModeMenuServices
*pFrameMenuServices
= NULL
;
577 WCHAR
* szText
= NULL
;
578 HMENU hMenuToAdd
= NULL
;
579 int menuItemCount
= 0;
581 CHECK_POINTER(m_pInPlaceFrame
);
583 // IE7's interface for creating and loading menus in Protected Mode (ONLY)
584 m_pInPlaceFrame
->QueryInterface(IID_IProtectedModeMenuServices
, (void**)&pFrameMenuServices
);
586 //Create an empty menu
587 Assert(m_hSharedMenu
== NULL
);
588 if(!pFrameMenuServices
)
590 m_hSharedMenu
= CreateMenu();
591 CK_ALLOC(m_hSharedMenu
);
595 CKHR(pFrameMenuServices
->CreateMenu(&m_hSharedMenu
));
597 // Let the Low Integrity IE process send us WM_MENUSELECT & WM_COMMAND.
598 // We prefer ChangeWindowMessageFilterEx(), which is new to Windows 7.
599 PFChangeWindowMessageFilterEx pfCWMF
= 0;
600 GetProcAddress(L
"User32.dll", "ChangeWindowMessageFilterEx", &pfCWMF
);
603 pfCWMF
= CallOldChangeWindowMessageFilter
;
605 HWND hwnd
= m_pOleDoc
->m_hwndTop
;
606 BOOL res
= (*pfCWMF
)(hwnd
, WM_MENUSELECT
, MSGFLT_ADD
, 0);
607 ASSERT(res
); (void)res
;
608 (*pfCWMF
)(hwnd
, WM_INITMENUPOPUP
, MSGFLT_ADD
, 0);
609 (*pfCWMF
)(hwnd
, WM_COMMAND
, MSGFLT_ADD
, 0);
612 //Zero out the merged menu array per OLE spec
613 ZeroMemory(&m_MenuGroupWidth
, sizeof(m_MenuGroupWidth
));
615 //Call container to insert its menus
616 CKHR(m_pInPlaceFrame
->InsertMenus(m_hSharedMenu
, &m_MenuGroupWidth
));
618 // Remove the "Go To" menu
619 // The items under "home" on this menu are added later by the browser frame. If we
620 // remove this item from the menu they will not be added because the browser cannot
622 // CKHR(RemoveMenu(m_hSharedMenu, 33104, MF_BYCOMMAND));
625 if(!pFrameMenuServices
)
627 CKHR(LoadMenuFromMuiResource(&m_hDocObjMenu
));
631 wchar_t dllPath
[MAX_PATH
];
632 CHECK_NULL_FROM_WIN32(GetModuleFileName(g_hInstance
, dllPath
, MAX_PATH
));
633 CKHR(pFrameMenuServices
->LoadMenuID(
634 dllPath
, GetMenuResourceId(m_pOleDoc
->GetCurrentMime()), &m_hDocObjMenu
));
637 CHECK_ZERO_FROM_WIN32(menuItemCount
= GetMenuItemCount(m_hDocObjMenu
));
638 szText
= new WCHAR
[MAX_PATH
+1];
641 // Add each menu in our resources to the shared menu. Adding them in reverse order ensures that they
642 // appear in a logical order when displayed
643 for (int menuItemIndex
= (menuItemCount
-1); menuItemIndex
> -1; menuItemIndex
--)
645 // get the menu from the loaded set of menus
646 hMenuToAdd
= GetSubMenu(m_hDocObjMenu
, menuItemIndex
);
647 CHECK_POINTER(hMenuToAdd
);
649 // If this is our 'View' menu
650 if (menuItemIndex
== 1)
652 // keep track of the view menu so we can check/uncheck the "Status Bar" and "Full Screen" items.
653 m_hViewMenu
= hMenuToAdd
;
655 // Determine the check state of the Status Bar and Full Screen menu options
656 SetViewMenuItemsCheckState(hMenuToAdd
);
659 // Add the menu to the shared menus using the name it was given in the resource
660 CHECK_ZERO_FROM_WIN32(GetMenuString(m_hDocObjMenu
, menuItemIndex
, szText
, MAX_PATH
+1, MF_BYPOSITION
));
661 CHECK_BOOL_FROM_WIN32(InsertMenu(m_hSharedMenu
,
662 m_MenuGroupWidth
.width
[0],
663 MF_BYPOSITION
| MF_POPUP
,
664 (UINT_PTR
) hMenuToAdd
,
667 // update the OLEMENUGROUPWIDTHS
668 m_MenuGroupWidth
.width
[1] += 1;
671 // Get the Ole menu descriptor
672 CHECK_NULL_FROM_WIN32(m_hOleMenu
= OleCreateMenuDescriptor(m_hSharedMenu
, &m_MenuGroupWidth
));
675 // Set the Menu on the container's frame
677 // The window passed here should be the one from our IOleInPlaceActiveObject->GetWindow
678 // As long as we are a single-instance server, this is okay.
679 // If not, we need to create a window per View/InplaceActiveObj to handle messages from this menu
680 CKHR(m_pOleDoc
->GetWindow(&hwnd
));
681 CKHR(m_pInPlaceFrame
->SetMenu(m_hSharedMenu
, m_hOleMenu
, hwnd
));
683 /* //Testing - Adding a menu item to container owned menu group
684 // Can Add successfully, but we don't get QueryStatus and Exec calls for it
686 hSubMenu = GetSubMenu(m_hSharedMenu,0);
687 int nItems = GetMenuItemCount(hSubMenu);
689 MENUITEMINFOW mii = { sizeof(mii) };
691 mii.fMask = MIIM_ID | MIIM_TYPE;
692 mii.wID = IDM_MENU_LAST+100;
693 mii.fType = MFT_RADIOCHECK | MFT_STRING;
694 mii.dwTypeData = L"Test";
695 mii.cch = lstrlenW(L"Test");
698 result = InsertMenuItemW(hSubMenu, nItems, TRUE, &mii);
701 /* // TESTING Disable a menu item on a container owned menu
702 //Can enable/disable container owned menus using Windows APIs incase we don't get QueryStatus
703 //but we cannot handle the WM_COMMAND for these menu items
705 hSubMenu = GetSubMenu(m_hSharedMenu,0);
707 EnableMenuItem(hSubMenu, 0, MF_BYPOSITION | MF_GRAYED);
709 m_pInPlaceFrame->SetMenu(m_hSharedMenu, m_hOleMenu, m_pOleDoc->m_hwndTop);
712 EventWriteWpfHostUm_MergingMenusEnd();
716 ReleaseInterface(pFrameMenuServices
);
719 DestroyMenuResources();
726 //******************************************************************************
728 // COleDocumentView::LoadMenuFromMuiResource()
730 //******************************************************************************
732 COleDocumentView::LoadMenuFromMuiResource(__out_ecount(1) HMENU
* menu
)
735 HINSTANCE hResourceInstance
= LoadResourceDLL();
736 CHECK_POINTER(hResourceInstance
);
738 //Load the docobj menus for our mime type. hr is set to S_OK or HRESULT_FROM_WIN32(GetLastError())
739 Assert(m_hDocObjMenu
== NULL
);
740 *menu
= LoadMenu(hResourceInstance
, MAKEINTRESOURCE(GetMenuResourceId(m_pOleDoc
->GetCurrentMime())));
741 CHECK_POINTER(*menu
);
744 FreeMUILibrary(hResourceInstance
);
748 //******************************************************************************
750 // COleDocumentView::SetViewMenuItemsCheckState()
752 //******************************************************************************
754 COleDocumentView::SetViewMenuItemsCheckState(HMENU viewMenu
)
757 IWebBrowser2
* pWebBrowserTop
= NULL
;
758 VARIANT_BOOL varBool
;
761 CKHR(GetTopLevelBrowser(m_pOleDoc
->GetClientSite(), &pWebBrowserTop
));
764 CKHR(pWebBrowserTop
->get_StatusBar(&varBool
));
765 uCheck
= (varBool
== VARIANT_TRUE
? MF_CHECKED
: MF_UNCHECKED
);
766 CheckMenuItem(viewMenu
, IDM_VIEW_STATUSBAR
, MF_BYCOMMAND
| uCheck
);
768 // check View Full Screen
769 CKHR(pWebBrowserTop
->get_TheaterMode(&varBool
));
770 uCheck
= (varBool
== VARIANT_TRUE
? MF_CHECKED
: MF_UNCHECKED
);
771 CheckMenuItem(viewMenu
, IDM_VIEW_FULLSCREEN
, MF_BYCOMMAND
| uCheck
);
774 ReleaseInterface(pWebBrowserTop
);
778 //******************************************************************************
780 // COleDocumentView::RemoveMergedMenus()
782 //******************************************************************************
783 void COleDocumentView::RemoveMergedMenus()
785 int menuItemCount
= 0;
787 if (m_hSharedMenu
== NULL
)
789 Assert(m_hDocObjMenu
== NULL
);
790 Assert(m_hOleMenu
== NULL
);
794 //Remove the DocObj menus first
795 menuItemCount
= GetMenuItemCount(m_hDocObjMenu
);
796 for (int index
=0; index
< menuItemCount
; index
++)
798 RemoveMenu(m_hSharedMenu
, m_MenuGroupWidth
.width
[0], MF_BYPOSITION
);
801 //Remove the container's menus next
802 m_pInPlaceFrame
->RemoveMenus(m_hSharedMenu
);
804 //Destroy resources since we are not going to reuse the menu handles
805 DestroyMenuResources();
808 void COleDocumentView::DestroyMenuResources()
810 //Destroy the shared menu handle
813 DestroyMenu(m_hSharedMenu
);
814 m_hSharedMenu
= NULL
;
817 //Destroy our local docobj menu handle
820 DestroyMenu(m_hDocObjMenu
);
821 m_hDocObjMenu
= NULL
;
822 // The 'view' menu is just part of m_hDocObjMenu and
823 // does not need to be destroyed separately.
827 //Destroy the Ole menu descriptor
830 OleDestroyMenuDescriptor(m_hOleMenu
);